#include "record_record_impl.h"
#include <mutex>
#include <unordered_map>
#include <sstream>
#include "base_log.h"
#include "common_config_manager.h"
#include "common_media_define.h"
#include "record_recorder.h"
#include <functional>
#include "record_search_cache.h"
#include "common_event.h"

namespace El {
namespace Record {

IRecord &IRecord::GetInstance()
{
    static CRecordImpl instance;
    return instance;
}

CRecordImpl::CRecordImpl() {}

CRecordImpl::~CRecordImpl() {}

bool CRecordImpl::Start()
{
    if (isStart_) {
        LOG_WARN("record already started");
        return true;
    }
    isStart_ = true;

    // 监听配置变化
    registerRcordHandle_ =
        Common::ConfigManager::GetInstance().RegisterVerify("record", [this](const nlohmann::json &config) {
            LOG_INFO("record config changed: {}", config.dump().c_str());
            ResetConfig(recordConfig_, config);
            return true;
        });
    registerStorageHandle_ =
        Common::ConfigManager::GetInstance().RegisterVerify("storage", [this](const nlohmann::json &config) {
            LOG_INFO("storage config changed: {}", config.dump().c_str());
            storageConfig_ = config;
            return true;
        });

    // 读取配置文件
    recordConfig_ = Common::ConfigManager::GetInstance().GetConfig("record");
    if (recordConfig_.empty()) {
        LOG_ERROR("record config is empty");
    }
    storageConfig_ = Common::ConfigManager::GetInstance().GetConfig("storage");
    if (storageConfig_.empty()) {
        LOG_ERROR("storage config is empty");
    }

    registerHandle_ = Storage::IStorageManager::GetInstance().RegisterStorageEventCallback(
        std::bind(&CRecordImpl::NotifyStorageEvent, this, std::placeholders::_1, std::placeholders::_2));
    Storage::IStorageManager::GetInstance().Start();

    return true;
}

void CRecordImpl::Stop()
{
    if (!isStart_) {
        LOG_WARN("record already stopped");
        return;
    }
    isStart_ = false;

    Storage::IStorageManager::GetInstance().UnregisterStorageEventCallback(registerHandle_);
    Common::ConfigManager::GetInstance().UnregisterVerify("record", registerRcordHandle_);
    Common::ConfigManager::GetInstance().UnregisterVerify("storage", registerStorageHandle_);
    Storage::IStorageManager::GetInstance().Stop();

    StopRecord();
}

bool CRecordImpl::StartRecord()
{
    if (isStartRecord_) {
        LOG_DEBUG("record already started");
        return true;
    }
    isStartRecord_ = true;

    LOG_INFO("record start");
    if (recordConfig_.empty() || !recordConfig_.contains("enable")) {
        LOG_ERROR("record config is empty");
        return false;
    }

    if (recordConfig_["enable"].get<bool>()) {
        // 启动录像服务
        for (uint32_t i = 0; i < CHANNEL_MAX; i++) {
            // 启动录像服务
            RecorderPtr recorder = std::make_shared<Recorder>(i);
            recorder->SetConfig(recordConfig_["maxFileDuration"].get<uint32_t>(),
                                recordConfig_["maxFileSize"].get<uint64_t>(),
                                storageConfig_["mountPath"].get<std::string>(), recordConfig_["overwrite"].get<bool>());
            if (recordConfig_["record"][i]["enable"].get<bool>()) {
                recorder->Start();
            }
            recorders_[i] = recorder;
        }
    } else {
        LOG_INFO("record is disabled");
    }

    return true;
}

void CRecordImpl::StopRecord()
{
    if (!isStartRecord_) {
        LOG_DEBUG("record already stopped");
        return;
    }
    isStartRecord_ = false;

    LOG_INFO("record stop");
    for (auto &recorder : recorders_) {
        recorder.second->Stop();
    }
    recorders_.clear();
}

bool CRecordImpl::ResetConfig(const nlohmann::json &oldConfig, const nlohmann::json &newConfig)
{
    // 如果关键配置发生变化，需要重启录像服务
    if (oldConfig["enable"] != newConfig["enable"]) {
        Stop();
        recordConfig_ = newConfig;
        return Start();
    }

    // 检查关键配置项是否发生变化
    if (oldConfig["maxFileDuration"] != newConfig["maxFileDuration"] ||
        oldConfig["maxFileSize"] != newConfig["maxFileSize"]) {
        for (uint32_t i = 0; i < CHANNEL_MAX; i++) {
            if (recorders_[i]) {
                recorders_[i]->SetConfig(
                    newConfig["maxFileDuration"].get<uint32_t>(), newConfig["maxFileSize"].get<uint64_t>(),
                    storageConfig_["mountPath"].get<std::string>(), newConfig["overwrite"].get<bool>());
            }
        }
    }
    recordConfig_ = newConfig;

    return true;
}

void CRecordImpl::NotifyStorageEvent(const std::shared_ptr<Storage::IStorageDevice> &device,
                                     Storage::DeviceStatus status)
{
    LOG_DEBUG("NotifyStorageEvent: {} {}", device->GetDevicePath(), Storage::DeviceStatusToString(status));
    storageEventType_ = status;
    if (status == Storage::DeviceStatus::ERR_MOUNTED) {
        StartRecord();
        RecordSearchCache::GetInstance().Start();
    } else if (status == Storage::DeviceStatus::ERR_UNMOUNTED) {
        StopRecord();
        RecordSearchCache::GetInstance().Stop();
    } else if (status == Storage::DeviceStatus::ERR_CAPACITY_WARNING) {
        // 获取录像配置中的overwrite设置
        bool overwrite = recordConfig_["overwrite"].get<bool>();
        if (overwrite) {
            // 如果开启了循环覆盖,删除最旧的文件
            LOG_INFO("Storage space low, deleting oldest files");
            RecordSearchCache::GetInstance().DeleteOldestFile();
        }
    } else if (status == Storage::DeviceStatus::ERR_CAPACITY_FULL) {
        // 存储容量满,停止录像
        LOG_INFO("Storage space full, stopping recording");
        StopRecord();
    } else if (status == Storage::DeviceStatus::ERR_CAPACITY_NORMAL) {
        // 存储容量恢复正常,重新启动录像
        LOG_INFO("Storage space returned to normal, restarting recording");
        StartRecord();
    }
}

int32_t CRecordImpl::StartManual(uint32_t ch)
{
    if (ch >= CHANNEL_MAX) {
        LOG_ERROR("channel {} is invalid", ch);
        return -1;
    }

    Storage::DeviceStatus status;
    Storage::IStorageManager::GetInstance().GetDefaultUdiskStatus(status);
    if (status != Storage::DeviceStatus::ERR_MOUNTED && status != Storage::DeviceStatus::ERR_CAPACITY_NORMAL) {
        LOG_ERROR("Udisk is not normal {}", Storage::DeviceStatusToString(status));
        return (int32_t)status;
    }

    auto recorder = recorders_[ch];
    if (!recorder) {
        LOG_ERROR("recorder for channel {} is not found", ch);
        return -1;
    }
    recorder->StartManual();
    return ERR_OK;
}

void CRecordImpl::StopManual(uint32_t ch)
{
    if (ch >= CHANNEL_MAX) {
        LOG_ERROR("channel {} is invalid", ch);
        return;
    }

    auto recorder = recorders_[ch];
    if (!recorder) {
        LOG_ERROR("recorder for channel {} is not found", ch);
        return;
    }

    recorder->StopManual();
}

bool CRecordImpl::GetRecordStatus(uint32_t ch)
{
    if (ch >= CHANNEL_MAX) {
        LOG_ERROR("channel {} is invalid", ch);
        return false;
    }

    auto recorder = recorders_[ch];
    if (!recorder) {
        LOG_ERROR("recorder for channel {} is not found", ch);
        return false;
    }

    return recorder->GetRecordStatus();
}

} // namespace Record
} // namespace El